﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace GeoFly
{
    /// <summary>
    /// 空间插值类
    /// </summary>
    public abstract class SpatialInterpolate
    {
        /// <summary>
        /// 插值样本点的X坐标序列
        /// </summary>
       public double[] X ;
         /// <summary>
        /// 插值样本点的Y坐标序列
        /// </summary>
       public     double[] Y ;
         /// <summary>
        /// 插值样本点的Z坐标序列
        /// </summary>
       public     double[] Z ;
        /// <summary>
        /// 将UTM坐标信息及高程信息直接存入数组，以便插值时加快速度
        /// </summary>
        /// <param name="date"></param>
        public void PrepareFromUTM(DateTime date)
        {
            if (this.pStationinfo == null || this.pMeteoData == null)
                throw new Exception("没有插值样本点");
                       
            //先将站点数据提出，以加快检索效率
             X = new double[pStationinfo.Count];
             Y = new double[pStationinfo.Count];
             Z = new double[pStationinfo.Count];
            for (int i = 0; i < this.pStationinfo.Keys.Count; i++)
            {
                string key = this.pStationinfo.Keys[i];
                X[i] = this.pStationinfo[key].X;
                Y[i] = this.pStationinfo[key].Y;
                Z[i] = this.pMeteoData[key][date];
            }
        }
        /// <summary>
        /// 将经纬度坐标信息转化为UTM坐标，并将UTM坐标及高程信息直接存入数组，以便插值时加快速度
        /// </summary>
        /// <param name="date"></param>
        public void PrepareFromLongLa(DateTime date)
        {
            if (this.pStationinfo == null || this.pMeteoData == null)
                throw new Exception("没有插值样本点");
            //先将站点数据提出，以加快检索效率
            X = new double[pStationinfo.Count];
            Y = new double[pStationinfo.Count];
            Z = new double[pStationinfo.Count];
            MapCoordConvertor conv = new MapCoordConvertor();
            for (int i = 0; i < this.pStationinfo.Keys.Count; i++)
            {
                string key = this.pStationinfo.Keys[i];
                double[] xy = conv.ToXY_UTM(this.pStationinfo[key].X, this.pStationinfo[key].Y);
                X[i] = xy[0];
                Y[i] = xy[1];
                Z[i] = this.pMeteoData[key][date];
            }
        }

        //输入参数
        public void SetExtentInfo(MapExtent extent, double gridresolustion)
        {
            //mapextent = extent.Copy();
            //m_dGridResolusion = gridresolustion;
            //m_gridLayer.Extent=extent.Copy();
            //m_gridLayer.resolution = gridresolustion;
        }
        
        /// <summary>
        /// 读入站点位置
        /// 站点位置文件的格式如下：
        /// ----------------------------------------
        /// 站名     X坐标    Y坐标     高程(可选)
        /// 刘家庄    118      35       250
        /// ...
        /// ...
        /// ------------------------------------------
        /// </summary>
        /// <param name="FileName">站点位置文件名</param>
        /// <param name="splitsymbol"></param>
        /// <returns></returns>
        public void ReadInStationPos(string FileName)
        {
            StreamReader sr = new StreamReader(FileName);
            pStationinfo = new SortedList<string, StationInfo>();
            //第一行认为是字段描述，绕过，不处理
            sr.ReadLine();
            //从第二行开始读起
            while (!sr.EndOfStream)
            {
                string[] line= sr.ReadLine().Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                StationInfo Station = new StationInfo();
                Station.StationName = line[0];
                Station.X = Convert.ToDouble(line[1]);
                Station.Y = Convert.ToDouble(line[2]);
                if (line.Length > 3)
                    Station.Elev = Convert.ToDouble(line[3]);
                pStationinfo[line[0]]=Station;
            }
            sr.Close();
        }
        
        public void ReadInStationValue(string FileName)					//读入多个插值站点的时序气象数据
        {
            this.saDate.Clear();
            StreamReader sr = new StreamReader(FileName);
            this.pMeteoData = new SortedList<string, SortedList<DateTime, double>>();
            this.saStationName = new List<string>();
            //读入第一行，第3列及以后的数据都为站名
            string[] StationNames= sr.ReadLine().Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 2; i < StationNames.Length; i++)
            {
                this.saStationName.Add(StationNames[i]);
                this.pMeteoData[StationNames[i]] = new SortedList<DateTime, double>();
            }

            while (!sr.EndOfStream)
            {
                //读入一行
                string[] line= sr.ReadLine().Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                //处理日期和时间
                string[] dateStr= line[0].Split(new char[] { '-'}, StringSplitOptions.RemoveEmptyEntries);
                string[] timeStr=line[1].Split(new char[] { ':'}, StringSplitOptions.RemoveEmptyEntries);
                int year=Convert.ToInt16(dateStr[0]);
                int month=Convert.ToInt16(dateStr[1]);
                int day=Convert.ToInt16(dateStr[2]);
                int hour=Convert.ToInt16(timeStr[0]);
                DateTime dateTime = new DateTime(year, month, day, hour, 0, 0);
                this.saDate.Add(dateTime);
                for (int i = 2; i < line.Length; i++)
                {
                    pMeteoData[StationNames[i]][dateTime] = Convert.ToDouble(line[i]);
                }
            }
        }
        
    


        

        
        /// <summary>
        /// 栅格图层输出结果
        /// </summary>
        /// <param name="filename">文件名，扩展名为*.asc</param>
        /// <returns></returns>
        public bool WriteGridLayer(string filename)	//输出图层数据到*.asc文件
        {
            return false;
        }
        //单站点插值输出结果
        public bool WriteStation(WeatherData dataout)
        {
            return false;
        }

        /// <summary>
        /// 单站点插值数据（由其它站点插值而来）reserved
        /// </summary>
        public WeatherData m_StationValue;	
        /// <summary>
        /// 子流域时序气象插值结果
        /// </summary>
        public List<string> m_saSubValue;
        /// <summary>
        /// 子流域结果保存文件名
        /// </summary>
        public string m_strSubFile;
               
        /// <summary>
        /// 气象数据时间序列(日期)
        /// </summary>
        public List<DateTime> saDate=new List<DateTime>();						
        /// <summary>
        /// 气象数据时间序列（小时，主要用于存放时段降雨数据的时间段）
        /// </summary>
        public List<string> saTime=new List<string>();
        /// <summary>
        /// 栅格数据(如：栅格插值结果)
        /// </summary>
        public GridLayer m_gridLayer;

        /// <summary>
        /// 插值栅格图层范围
        /// </summary>
        public MapExtent mapextent;
        /// <summary>
        /// 栅格精度
        /// </summary>
        public double m_dGridResolusion;
        /// <summary>
        /// 气象数据  *** important
        /// pMeteoData[i,j] i: 气象站点号；j:日期
        /// </summary>
        public SortedList<string,SortedList<DateTime,double>> pMeteoData;
        /// <summary>
        /// 插值站点数
        /// </summary>
        public int stationnum;
        

        /// <summary>
        /// 被插值站点信息,由构造函数传入
        /// </summary>
        public StationInfo InterPose;	
        /// <summary>
        /// 插值站点信息，由站点文件读入。键值为站名
        /// </summary>
        public SortedList<string,StationInfo> pStationinfo;
        /// <summary>
        /// 气象数据文件中的气象站名
        /// </summary>
        public List<string> saStationName;
        /// <summary>
        /// 距离
        /// </summary>
        public double[] pDistance;
        /// <summary>
        /// 子流域数
        /// </summary>
        public int m_subbasinnum;
        public CoordType m_CoordType=CoordType.UTM_Coord;

    }
}
